package com.chenzhiling.study.util

import java.nio.ByteBuffer
import scala.annotation.tailrec
import scala.collection.mutable.ArrayBuffer


/**
 * @Author: CHEN ZHI LING
 * @Date: 2021/7/7
 * @Description: 字节数组工具类
 */
object ArrayByteUtil {

  /**
   * 单行可存储的最大字节数组大小
   * 512mb
   */
  private val ONE_ROW_MAX_ARRAY_SIZE: Int = 1024 * 1024 * 512

  /**
   * 每次读取1字节大小
   */
  private val READ_BYTE_ONE_TIME: Int = 1





  /**
   * 将一个数组按512Mb切分成若干个数组
   * 便利循环
   * @param array 字节数组
   * @return 切分后的数组
   */
  def splitArrayByteByMaxSize(array: Array[Byte]): List[Array[Byte]] ={
    //切分成至少一个数组
    val count: Int = if (array.length % ONE_ROW_MAX_ARRAY_SIZE == 0) array.length / ONE_ROW_MAX_ARRAY_SIZE else array.length / ONE_ROW_MAX_ARRAY_SIZE + 1
    val result = new ArrayBuffer[Array[Byte]]()

    for (i <- 0 until count ){
      var index: Int = i * ONE_ROW_MAX_ARRAY_SIZE-1
      val subList = new ArrayBuffer[Byte]()
      var j = 0
      //循环读取，防止内存溢出
      while ( j < ONE_ROW_MAX_ARRAY_SIZE && index < array.length-1) {
        subList += array({index += 1;index})
        j += READ_BYTE_ONE_TIME
      }
      result.append(subList.toArray)
    }
    result.toList
  }
  /**
   * 将一个数组按512Mb切分成若干个数组
   * System.arrayCopy方法
   * @param array 字节数组
   * @return 切分后的数组
   */
  def splitArray(array: Array[Byte]): List[Array[Byte]] = {
    val numOfChunks: Int = Math.ceil(array.length.toDouble / ONE_ROW_MAX_ARRAY_SIZE).toInt
    val result = new ArrayBuffer[Array[Byte]]()
    for (i <- 0 until numOfChunks) {
      val start: Int = i * ONE_ROW_MAX_ARRAY_SIZE
      val length: Int = Math.min(array.length - start, ONE_ROW_MAX_ARRAY_SIZE)
      val subArray = new Array[Byte](length)
      System.arraycopy(array, start, subArray, 0, length)
      result.append(subArray)
    }
    result.toList
  }




  /**
   * 将n个字节数组合并成一个
   * @param list 数组
   * @return array[Byte]
   */
  @tailrec
  def joinArray(list:List[Array[Byte]]): Array[Byte] ={
    val length: Int = list.length
    if (2==length){
      return joinTwoArray(list.head,list.last)
    }
    //将前两个合并
    val bytes: Array[Byte] = joinTwoArray(list.head, list(1))
    //push掉前两个元素
    val tail: List[Array[Byte]] = list.tail.tail
    //组成新的集合
    val newList: List[Array[Byte]] = bytes :: tail
    //递归合并
    joinArray(newList)
  }

  /**
   * 将两个字节数组拼接
   * @param arrayOne 字节数组One
   * @param arrayTwo 字节数组Two
   * @return
   */

  def joinTwoArray(arrayOne: Array[Byte],arrayTwo: Array[Byte]): Array[Byte] ={
    val bytes: Array[Byte] = ByteBuffer.allocate(arrayOne.length + arrayTwo.length)
      .put(arrayOne)
      .put(arrayTwo).array()
    bytes
  }


  def main(args: Array[String]): Unit = {
    val bt = new Array[Byte](10)
    for (i <- 0 until 10) {
      bt(i) = i.toByte
    }
    val lists: List[Array[Byte]] = splitArrayByteByMaxSize(bt)
    for (elem <- lists) {
      println(elem.mkString("Array(", ", ", ")"))
    }
  }





}
